package cn.itsource.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.itsource.api.openfeign.ILoginOpenFeignClient;
import cn.itsource.constants.CacheConstants;
import cn.itsource.constants.ErrorCode;
import cn.itsource.constants.RConst;
import cn.itsource.pojo.domain.Driver;
import cn.itsource.mapper.DriverMapper;
import cn.itsource.pojo.domain.DriverAggrement;
import cn.itsource.pojo.domain.DriverSetting;
import cn.itsource.pojo.domain.DriverSummary;
import cn.itsource.pojo.dto.RegisterDto;
import cn.itsource.pojo.ro.DriverOnLineRo;
import cn.itsource.pojo.ro.GeoRo;
import cn.itsource.pojo.ro.LoginRo;
import cn.itsource.pojo.ro.WxChatRegisterRo;
import cn.itsource.result.JSONResult;
import cn.itsource.service.*;
import cn.itsource.utils.AssertUtil;
import cn.itsource.utils.BitStatesUtils;
import cn.itsource.utils.NameUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 司机对象 服务实现类
 * </p>
 *
 * @author zcj
 * @since 2024-07-02
 */
@Service
@Slf4j
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements IDriverService {
    @Autowired
    private IDriverAggrementService driverAggrementService;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private ILoginOpenFeignClient loginOpenFeignClient;
    @Autowired
    private IDriverSummaryService driverSummaryService;
    @Autowired
    private IDriverSettingService driverSettingService;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 实现业务逻辑
     * @param registerRo
     * @return
     */
    @Override
//    @Transactional
    @GlobalTransactional
    public JSONResult wxChatRegister(WxChatRegisterRo registerRo) {
        RegisterDto registerDto = weChatService.getWeChatOpenId(registerRo.getCode());
//        String userPhone = weChatService.getUserPhone(registerRo.getPhoneCode());
        String userPhone = "18723001111";
        //先判断 如果已经存在那么久不保存
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, registerDto.getOpenid()));
        if(one == null){
            initDriver(registerDto,userPhone);
            //发送的请求
            JSONResult login = loginOpenFeignClient.createLogin(buildLoginRo(registerDto, userPhone));
//            int i=1/0;
            AssertUtil.isTrue(login.isSuccess(),"微信绑定失败");

            return JSONResult.message("微信绑定成功");
        }
        return JSONResult.error(ErrorCode.WE_CHAT_REPEAT_ERROR);
    }

    @Override
    public DriverSetting driverOnLine(DriverOnLineRo onLineRo) {
        //干什么事情？
        String openId = StpUtil.getExtra("openId").toString();
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openId));
        //注意一个司机只有一个配置  初始化就有
        DriverSetting setting = driverSettingService.getById(one.getId());
        //将我们的司机的配置缓存到redis里面  是因为后面我们有乘客来了 根据配置做事情  10公里 当前区域外的
        String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING, one.getId());
        redisTemplate.opsForValue()
                .set(key,setting,RConst.Num.INT_5, TimeUnit.MINUTES);
        //坐标记录到redis 里面去
        return setting;
    }

    /**
     * 司机下线
     */
    @Override
    public void driverOffLine() {
        String openId = StpUtil.getExtra("openId").toString();
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openId));
        String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING, one.getId());
        redisTemplate.delete(key);
    }

    @Override
    public void geo(GeoRo geoRo) {
        //获取当前登录的司机id
        String openId = StpUtil.getExtra("openId").toString();
        Driver one = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openId));
        //获取小程序 提交的坐标
        Point point = new Point(Double.valueOf(geoRo.getLongitude()),Double.valueOf(geoRo.getLatitude()));
        //将坐标缓存到geo里面
        Long add = redisTemplate.opsForGeo().add(CacheConstants.KEY_DRIVER_GEO, point, one.getId());//处理地理位置的
        //判断是否添加成功
        if(add == RConst.Num.LONG_1){
            //刷新司机的状态
            String key = String.format(CacheConstants.KEY_DRIVER_ONLINE_SETTING, one.getId());
            redisTemplate.expire(key,RConst.Num.INT_5,TimeUnit.MINUTES);
        }
    }

    private static LoginRo buildLoginRo(RegisterDto registerDto,String phone) {
        LoginRo loginRo = new LoginRo();
        loginRo.setPassword("123456");//todo
        loginRo.setType(RConst.Num.INT_1);
        loginRo.setOpenId(registerDto.getOpenid());
        loginRo.setPhone(phone);
        loginRo.setUsername(NameUtil.getName());//todo
        loginRo.setAdmin(false);
        return loginRo;
    }

    private void initDriver(RegisterDto registerDto,String phone) {
        long state = BitStatesUtils.addState(RConst.Num.BASE_LONG_0, BitStatesUtils.OP_PHONE);
        state = BitStatesUtils.addState(state, BitStatesUtils.OP_INIT_PAY_PASSWORD);
        //主表
        Long driverId = IdUtil.createSnowflake(RConst.Num.INT_1, RConst.Num.INT_1).nextId();
        Driver driver = new Driver()
                .setId(driverId)
                .setCreateTime(new Date())
                .setPhone(phone)
                .setBitState(state)
                .setOpenId(registerDto.getOpenid());
        super.save(driver);
        //合同
        DriverAggrement driverAggrement = new DriverAggrement();
        driverAggrement.setId(IdUtil.createSnowflake(RConst.Num.INT_1, RConst.Num.INT_1).nextId());
        driverAggrement.setDriverId(driverId);
        driverAggrement.setStatus(RConst.Num.INT_0);
        driverAggrement.setCreateTime(new Date());
        driverAggrementService.save(driverAggrement);
        //当前司机的统计表
        DriverSummary driverSummary = new DriverSummary();
        driverSummary.setId(driverId);
        driverSummaryService.save(driverSummary);
    }
}
